package com.regex.web.controller.gen;


import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.regex.web.common.excel.ExportExcel;
import com.regex.web.entity.gen.DatabaseDTO;
import com.regex.web.entity.gen.FieldInfoDTO;
import com.regex.web.entity.gen.TableInfoDTO;
import com.regex.web.service.gen.IDatabaseService;
import com.regex.web.service.gen.IFieldInfoService;
import com.regex.web.service.gen.ITableInfoService;
import com.regex.web.utils.AjaxUtil;
import com.regex.web.utils.Contant;
import com.regex.web.utils.QueryResult;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author ocean.ma
 * @since 2019-07-23
 */
@Controller
@RequestMapping("sys/fieldInfo")
public class FieldInfoController {

	private final static Logger logger = LoggerFactory.getLogger(FieldInfoController.class);
	
	@Autowired
	private IFieldInfoService IFieldInfoService;
	
	@Autowired
	private ITableInfoService ITableInfoService;
	
	@Autowired
	private IDatabaseService IDatabaseService;
	
	/**
	 * 分页查询
	 * @param page
	 * @param model
	 * @param fieldInfoDTO
	 * @return
	 */
	@RequestMapping("show")
	public String show(Page<FieldInfoDTO> page, Model model,@ModelAttribute("fieldInfoDTO") FieldInfoDTO fieldInfoDTO) {
		try {
			QueryWrapper<FieldInfoDTO> param = new QueryWrapper<FieldInfoDTO>();
	        QueryResult<FieldInfoDTO> result = IFieldInfoService.page(page, param);
	        model.addAttribute("result", result);
        } catch (Exception e) {
			e.printStackTrace();
			logger.error("show page is Exception!");
		}
		return "sys/fieldInfo/show";
	}
	
	/**
	 * 编辑/新增
	 * @param id
	 * @param model
	 * @return
	 */
	@RequestMapping("input")
    public String toSave(String id, Model model) {
    	try {
	        if(StringUtils.isNotEmpty(id)) {
	        	FieldInfoDTO fieldInfoDTO = IFieldInfoService.getById(id);
	            model.addAttribute("fieldInfoDTO", fieldInfoDTO);
	        }
        } catch (Exception e) {
			e.printStackTrace();
			logger.error("toSave page is Exception!");
		}
        return "sys/fieldInfo/input";
    }
	
	@RequestMapping("saveList")
	public void saveList(String fields, String tableName, String dbId, HttpServletResponse response) {
		boolean flag = false;
		try {
			List<FieldInfoDTO> fieldLists = JSON.parseArray(fields, FieldInfoDTO.class);
			DatabaseDTO database = IDatabaseService.getById(dbId);
			if(database != null) {
				
			}
			QueryWrapper<TableInfoDTO> queryWrapper = new QueryWrapper<TableInfoDTO>();
			queryWrapper.eq("db_id", dbId);
			queryWrapper.eq("table_name", tableName);
			TableInfoDTO tableInfoDTO = ITableInfoService.getOne(queryWrapper);
			
//			QueryWrapper<FieldInfoDTO> queryWrapper2 = new QueryWrapper<FieldInfoDTO>();
//			queryWrapper2.eq("table_id", tableInfoDTO.getId());
//			IFieldInfoService.remove(queryWrapper2);
			
			for(FieldInfoDTO fieldInfoDTO : fieldLists) {
				QueryWrapper<FieldInfoDTO> fieldInfoQuery = new QueryWrapper<FieldInfoDTO>();
				fieldInfoQuery.eq("table_id", tableInfoDTO.getId());
				fieldInfoQuery.eq("capital_name", fieldInfoDTO.getCapitalName());
				FieldInfoDTO fieldInfoData = IFieldInfoService.getOne(fieldInfoQuery);
				if(fieldInfoData != null) {
					fieldInfoDTO.setId(fieldInfoData.getId());
					fieldInfoDTO.setUpdateTime(new Date());
					IFieldInfoService.updateById(fieldInfoDTO);
				} else {
					fieldInfoDTO.setTableId(tableInfoDTO.getId());
					fieldInfoDTO.setIsDel(Contant.is_del_undelete);
					fieldInfoDTO.setUpdateTime(new Date());
					fieldInfoDTO.setCreateTime(new Date());
					IFieldInfoService.save(fieldInfoDTO);
				}
			}
			
			createCode(database, tableInfoDTO, fieldLists);
			flag = true;
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("save page is Exception!");
		}
		int n = 0;
		if(flag) {
			n = 1;
		}
		AjaxUtil.ajaxJsonSucMessage(response, n);
	}
	
	
	public void createCode(DatabaseDTO database, TableInfoDTO tableInfoDTO, List<FieldInfoDTO> fieldLists) {
//      assert (false) : "代码生成属于危险操作，请确定配置后取消断言执行代码生成！";
      AutoGenerator mpg = new AutoGenerator();
      // 选择 freemarker 引擎，默认 Velocity
      mpg.setTemplateEngine(new FreemarkerTemplateEngine());
      // 全局配置
      GlobalConfig gc = new GlobalConfig();
      /**
       * 设置id为全局唯一变量
       */
      if(StringUtils.isNotEmpty(tableInfoDTO.getTableIdType())) {
    	  if("0".equals(tableInfoDTO.getTableIdType())) {
    		  gc.setIdType(IdType.AUTO);
    	  } else if("1".equals(tableInfoDTO.getTableIdType())) {
    		  gc.setIdType(IdType.NONE);
    	  } else if("2".equals(tableInfoDTO.getTableIdType())) {
    		  gc.setIdType(IdType.INPUT);
    	  } else if("3".equals(tableInfoDTO.getTableIdType())) {
    		  gc.setIdType(IdType.ID_WORKER);
    	  } else if("4".equals(tableInfoDTO.getTableIdType())) {
    		  gc.setIdType(IdType.UUID);
    	  } else if("5".equals(tableInfoDTO.getTableIdType())) {
    		  gc.setIdType(IdType.ID_WORKER_STR);
    	  }
      } else {
    	  gc.setIdType(IdType.ID_WORKER_STR);
      }
//      gc.seti
      if(StringUtils.isNotEmpty(tableInfoDTO.getAuthor())) {
    	  gc.setAuthor(tableInfoDTO.getAuthor());
      } else {
    	  gc.setAuthor("ocean.ma");
      }
      if(StringUtils.isNotEmpty(tableInfoDTO.getOutPutDir())) {
    	  gc.setOutputDir(tableInfoDTO.getOutPutDir());  
      } else {
    	  gc.setOutputDir(tableInfoDTO.getOutPutDir() + "");
      }
      gc.setFileOverride(true);// 是否覆盖同名文件，默认是false
      gc.setActiveRecord(true);// 不需要ActiveRecord特性的请改为false
      gc.setEnableCache(false);// XML 二级缓存
      gc.setBaseResultMap(true);// XML ResultMap
      gc.setBaseColumnList(false);// XML columList
      /* 自定义文件命名，注意 %s 会自动填充表实体属性！ */
      gc.setEntityName("%sDTO");
       gc.setMapperName("%sDAO");
      // gc.setXmlName("%sDao");
      // gc.setServiceName("MP%sService");
      // gc.setServiceImplName("%sServiceDiy");
      // gc.setControllerName("%sAction");
       mpg.setGlobalConfig(gc);

      // 数据源配置
      DataSourceConfig dsc = new DataSourceConfig();
      if("0".equals(database.getDbType())) {
    	  dsc.setDbType(DbType.MYSQL);
      } else if("1".equals(database.getDbType())) {
    	  dsc.setDbType(DbType.MARIADB);
      } else if("2".equals(database.getDbType())) {
    	  dsc.setDbType(DbType.ORACLE);
      } else if("3".equals(database.getDbType())) {
    	  dsc.setDbType(DbType.DB2);
      } else if("4".equals(database.getDbType())) {
    	  dsc.setDbType(DbType.SQL_SERVER2005);
      } else if("5".equals(database.getDbType())) {
    	  dsc.setDbType(DbType.SQL_SERVER);
      } 
      dsc.setTypeConvert(new MySqlTypeConvert() {
          // 自定义数据库表字段类型转换【可选】
          public DbColumnType processTypeConvert(String fieldType) {
              System.out.println("转换类型：" + fieldType);
              // 注意！！processTypeConvert 存在默认类型转换，如果不是你要的效果请自定义返回、非如下直接返回。
              return (DbColumnType) super.processTypeConvert(gc, fieldType);
          }
      });
//      dsc.setDriverName("com.mysql.jdbc.Driver");
//      dsc.setUsername("root");
//      dsc.setPassword("123456");
//      dsc.setUrl("jdbc:mysql://127.0.0.1:3306/base_db?useUnicode=true&characterEncoding=utf8");
      dsc.setDriverName(database.getDbDriverName());
      dsc.setUsername(database.getDbUserName());
      dsc.setPassword(database.getDbPassword());
      dsc.setUrl(database.getDbHost());
      mpg.setDataSource(dsc);

      // 策略配置
      StrategyConfig strategy = new StrategyConfig();
      // strategy.setCapitalMode(true);// 全局大写命名 ORACLE 注意
      String prefix = tableInfoDTO.getPrefix();
      if(StringUtils.isEmpty(prefix)) {
    	  prefix = "";
      }
      strategy.setTablePrefix(new String[] { prefix });// 此处可以修改为您的表前缀
      strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
//      strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//      strategy.setEntityLombokModel(true);
      String tableName = tableInfoDTO.getTableName();
      strategy.setInclude(new String[] { tableName }); // 需要生成的表
//      strategy.setLogicDeleteFieldName("is_del");
      // strategy.setExclude(new String[]{"test"}); // 排除生成的表
      // 自定义实体父类
      if(StringUtils.isNotEmpty(tableInfoDTO.getSuperEntity())) {
    	  strategy.setSuperEntityClass(tableInfoDTO.getSuperEntity());
    	  // i启用Lombok
      } else {
    	  // strategy.setSuperEntityClass("com.regex.web.entity.StrIdBaseEntity");
      }
      // lombok
      strategy.setEntityLombokModel(true);
      // 是否需要导出配置
      strategy.setEntityTableNeedExportFlag(true);
      // 自定义实体，公共字段
      if(StringUtils.isNotEmpty(tableInfoDTO.getCommonColumns())) {
    	  String commonColumns[] = tableInfoDTO.getCommonColumns().split(",");
    	  strategy.setSuperEntityColumns(commonColumns);
      } else {
    	  // strategy.setSuperEntityColumns(new String[] { "id", "is_del", "create_time", "update_time" });
      }
//      strategy.setcol
      // 自定义 mapper 父类
      // strategy.setSuperMapperClass("com.baomidou.demo.TestMapper");
      // 自定义 service 父类
      if(StringUtils.isNotEmpty(tableInfoDTO.getSuperService())) {
    	  strategy.setSuperServiceClass(tableInfoDTO.getSuperService());
      } else {
    	  strategy.setSuperServiceClass("com.regex.web.service.base.IBaseService");
      }
//       自定义 service 实现类父类
      if(StringUtils.isNotEmpty(tableInfoDTO.getSuperServiceImpl())) {
    	  strategy.setSuperServiceImplClass(tableInfoDTO.getSuperServiceImpl());
      } else {
    	  strategy.setSuperServiceImplClass("com.regex.web.service.base.impl.BaseServiceImpl");
      }
      // 自定义 controller 父类
//       strategy.setSuperControllerClass("com.baomidou.demo.TestController");
      // 【实体】是否生成字段常量（默认 false）
      // public static final String ID = "test_id";
//       strategy.setEntityColumnConstant(true);
      // 【实体】是否为构建者模型（默认 false）
      // public User setName(String name) {this.name = name; return this;}
//       strategy.setEntityBuilderModel(true);
       // 添加字段注解
       strategy.entityTableFieldAnnotationEnable(true);
      mpg.setStrategy(strategy);

      // 包配置
      PackageConfig pc = new PackageConfig();
//      pc.setModuleName("test");
//      String packageName = "member";
      if(StringUtils.isNotEmpty(tableInfoDTO.getPackageName())) {
    	  pc.setParent(tableInfoDTO.getParentPackage());  
      } else {
    	  pc.setParent("com.regex.web");
      }
      pc.setEntity("entity." + tableInfoDTO.getPackageName());
      pc.setService("service." + tableInfoDTO.getPackageName());
      pc.setServiceImpl("service." +tableInfoDTO.getPackageName() + ".impl");
      pc.setMapper("dao."+tableInfoDTO.getPackageName());
      pc.setXml("dao."+tableInfoDTO.getPackageName());
      pc.setController("controller."+ tableInfoDTO.getPackageName());
      // pc.setModuleName("test");
      mpg.setPackageInfo(pc);

      // 注入自定义配置，可以在 VM 中使用 cfg.abc 【可无】
       InjectionConfig cfg = new InjectionConfig() {
       @Override
       public void initMap() {
       Map<String, Object> map = new HashMap<String, Object>();
       map.put("abc", this.getConfig().getGlobalConfig().getAuthor() +
       "-mp");
       this.setMap(map);
       }
       };
      
       // 自定义 xxList.jsp 生成
       List<FileOutConfig> focList = new ArrayList<>();
       
       focList.add(new FileOutConfig("/templates/template/list.html.ftl") {
       @Override
       public String outputFile(TableInfo tableInfo) {
       // 自定义输入文件名称
       return tableInfoDTO.getOutPutDir() + "/page/" + tableInfo.getEntityPath().substring(0, tableInfo.getEntityPath().length() - 3) + "/show.html";
       }
       });
//       cfg.setFileOutConfigList(focList);
//       mpg.setCfg(cfg);
//      
//       // 调整 xml 生成目录演示
       focList.add(new FileOutConfig("/templates/template/input.html.ftl") {
       @Override
       public String outputFile(TableInfo tableInfo) {
       return tableInfoDTO.getOutPutDir() + "/page/" + tableInfo.getEntityPath().substring(0, tableInfo.getEntityPath().length() - 3) + "/input.html";
       }
       });
//       cfg.setFileOutConfigList(focList);
//       mpg.setCfg(cfg);
       
       focList.add(new FileOutConfig("/templates/template/detial.html.ftl") {
           @Override
           public String outputFile(TableInfo tableInfo) {
           return tableInfoDTO.getOutPutDir() + "/page/" + tableInfo.getEntityPath().substring(0, tableInfo.getEntityPath().length() - 3) + "/detial.html";
           }
           });
//           cfg.setFileOutConfigList(focList);
//           mpg.setCfg(cfg);
       // 新增rest接口代码生成
           
       focList.add(new FileOutConfig("/templates/template/restcontroller.java.ftl") {
       @Override
       public String outputFile(TableInfo tableInfo) {
       return tableInfoDTO.getOutPutDir() + "/" + tableInfoDTO.getParentPackage().replaceAll("\\.", "\\/") + "/rest/" + tableInfoDTO.getPackageName() + "/" + tableInfo.getEntityName().substring(0, tableInfo.getEntityPath().length() - 3) + "RestController.java";
       }
       });
       
       focList.add(new FileOutConfig("/templates/template/import.html.ftl") {
           @Override
           public String outputFile(TableInfo tableInfo) {
           return tableInfoDTO.getOutPutDir() + "/page/" + tableInfo.getEntityPath().substring(0, tableInfo.getEntityPath().length() - 3) + "/import_excel.html";
           }
           });
       
       cfg.setFileOutConfigList(focList);
       mpg.setCfg(cfg);
      //
      // // 关闭默认 xml 生成，调整生成 至 根目录
       TemplateConfig tc = new TemplateConfig();
      // tc.setXml(null);
      // mpg.setTemplate(tc);

      // 自定义模板配置，可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改，
      // 放置自己项目的 src/main/resources/templates 目录下, 默认名称一下可以不配置，也可以自定义模板名称
      // TemplateConfig tc = new TemplateConfig();
       tc.setController("/templates/template/controller.java");
       tc.setEntity("/templates/template/entity.java");
       tc.setMapper("/templates/template/mapper.java");
       tc.setXml("/templates/template/mapper.xml");
       tc.setService("/templates/template/service.java");
       tc.setServiceImpl("/templates/template/serviceImpl.java");
      // 如上任何一个模块如果设置 空 OR Null 将不生成该模块。
       mpg.setTemplate(tc);

      // 执行生成
      mpg.executeTmp(fieldLists, tableInfoDTO);

	}
    
    /**
	 * 保存
	 * @param fieldInfoDTO
	 * @param response
	 */
    @RequestMapping("save")
	public void save(FieldInfoDTO fieldInfoDTO, HttpServletResponse response) {
		boolean flag = false;
		try {
			if(StringUtils.isNotEmpty(fieldInfoDTO.getId())) {
				fieldInfoDTO.setUpdateTime(new Date());
				flag = IFieldInfoService.updateById(fieldInfoDTO);
			} else {
				fieldInfoDTO.setIsDel(Contant.is_del_undelete);
				fieldInfoDTO.setUpdateTime(new Date());
				fieldInfoDTO.setCreateTime(new Date());
				flag = IFieldInfoService.save(fieldInfoDTO);
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("save page is Exception!");
		}
		int n = 0;
		if(flag) {
			n = 1;
		}
		AjaxUtil.ajaxJsonSucMessage(response, n);
	}
	
	/**
	 * 详情
	 * @param id
	 * @param model
	 * @return
	 */
	@RequestMapping("detial")
    public String detial(String id, Model model) {
        try {
	        if(StringUtils.isNotEmpty(id)) {
	        	FieldInfoDTO fieldInfoDTO = IFieldInfoService.getById(id);
	            model.addAttribute("fieldInfoDTO", fieldInfoDTO);
	        }
        } catch (Exception e) {
			e.printStackTrace();
			logger.error("detial page is Exception!");
		}
        return "sys/fieldInfo/detial";
    }
	
	/**
	 * 删除
	 * @param id
	 * @param response
	 */
	@RequestMapping("del")
    public void del(String id, HttpServletResponse response) {
        int n = 0;
        try {
	        if(StringUtils.isNotEmpty(id)) {
	        	boolean flag = IFieldInfoService.removeById(id);
	        	if(flag) {
	        		n = 1;
	        	}
	        } else {
	        	n = 2;
	        }
        } catch (Exception e) {
			e.printStackTrace();
			logger.error("del page is Exception!");
		}
        AjaxUtil.ajaxJsonSucMessage(response, n);
    }
    
    /**
	 * 导出
	 * @param response
	 * @param fieldInfoDTO
	 * @return
	 */
    @RequestMapping(value = "export", method=RequestMethod.POST)
    public String exportFile(HttpServletResponse response, @ModelAttribute("fieldInfoDTO") FieldInfoDTO fieldInfoDTO) {
        try {
            QueryWrapper<FieldInfoDTO> param = new QueryWrapper<FieldInfoDTO>(fieldInfoDTO);
        	
        	String fileName = "数据"+(new Date()).getTime()+".xlsx";
            
            List<FieldInfoDTO> datas = IFieldInfoService.list(param);
            new ExportExcel("数据", FieldInfoDTO.class).setDataList(datas).write(response, fileName).dispose();
            return null; 
        } catch (Exception e) {
        	logger.error("exportFile page is Exception!");
            e.printStackTrace();
        }
        return "redirect:show.htm";
    }
	
}
